#ifndef __EXPR_H__
#define __EXPR_H__

#include <stdint.h>
#include <stdlib.h>
#include <memory.h>
#include "ast.h"
#include "type.h"

/**
 OPINFO(OP_LESS_EQ, 	  10,	"<=",	  Binary,		  JLE)
 OPINFO(OP_LSHIFT,		  11,	"<<",	  Binary,		  LSH)
 OPINFO(OP_RSHIFT,		  11,	">>",	  Binary,		  RSH)
 OPINFO(OP_ADD, 		  12,	"+",	  Binary,		  ADD)
 OPINFO(OP_SUB, 		  12,	"-",	  Binary,		  SUB)
 OPINFO(OP_MUL, 		  13,	"*",	  Binary,		  MUL)
 OPINFO(OP_DIV, 		  13,	"/",	  Binary,		  DIV)

 */
enum OP
{
#define OPINFO(op, prec, name, func, opcode) op,
#include "opinfo.h"
#undef OPINFO
};
/**
 Some tokens represent both unary and binary operator
e.g. 	*   +
 */
typedef struct
{
	/* token used as binary operator */
	int bop  : 16;
	/* token used as unary operator */
	int uop  : 16;
} token_op_t;

#define IS_BINARY(tok) (tok >= TK_OR && tok <= TK_MOD)
/* 
 token used as binary operator 
 */
#define	CUR_BINARY_OP()       g_token_op[tokc.kind - TK_ASSIGN].bop
/*
 token used as unary operator
 */
#define CUR_UNARY_OP()        g_token_op[tokc.kind - TK_ASSIGN].uop

const char* get_op_name(int op);

ast_node_t* parse_expression();

void print_expression(ast_node_t* node);

void print_expression_s(ast_node_t* node);

int expr_error_count();

ast_node_t* get_expr_errors();

void free_expr_errors();

void free_expression(ast_node_t* node);

struct expr_t: public ast_node_t
{
	type_t* ty;
	int op : 16;
	int isarray : 1;
	int isfunc  : 1;
	int lvalue  : 1;
	int bitfld  : 1;
	int inreg   : 1;
	int unused  : 11;
	expr_t *kids[2];
	value_t val;
    expr_t() {
        memset(this, 0, sizeof(*this));
    }
	~expr_t() {
		if (kids[0]) {
			delete kids[0];
			kids[0] = nullptr;
		}
		if (kids[1]) {
			delete kids[1];
			kids[1] = nullptr;
		}
		free_nodes(next);
	}
};

expr_t* parse_primary_expression();

expr_t* parse_postfix_expression(void);

expr_t* parse_unary_expression();

expr_t* parse_binary_expression(int prec);

expr_t* parse_cond_expression();

expr_t* parse_constant_expression(void);

extern "C" expr_t* parse_assign_expression();


#endif  // __EXPR_H__
